#include "bang_robot_service.h"

#include "base/logging.h"

#include "shop_info_cache.h"
#include "area_index.h"
#include "dispatch_message_task.h"
#include "dispatch_presence_task.h"

#include "im/adapters/session_adapter.h"
#include "im/adapters/message_outlet_adapter.h"

namespace imserver {

using apache::thrift::concurrency::Runnable;

class BroadcastClientTask : public Runnable  {
 public:
  BroadcastClientTask(const int64_t uid, const int64_t inactive_shop) : uid_(uid), inactive_shop_(inactive_shop) {}
  virtual void run();
 protected:
  int GetOnlineNeighborShops(const std::string & city_code, const std::string & area_code, 
    const std::string & quan_code, std::vector<int64_t> * ret) const;
  int64_t uid_;
  int64_t inactive_shop_;
};

class BroadcastClientWithQuestionTask : public BroadcastClientTask  {
 public:
  BroadcastClientWithQuestionTask(const int64_t uid, const int64_t inactive_shop, const std::string& question)
    : BroadcastClientTask(uid, inactive_shop), question_(question) {}
  virtual void run();
 private:
  std::string question_;
};

int BroadcastClientTask::GetOnlineNeighborShops(const std::string & city_code, const std::string & area_code, 
    const std::string & quan_code, std::vector<int64_t> * ret) const {
  std::set<int64_t> neighbors = AreaIndex::Instance().Get(city_code, area_code, quan_code);
  // 抽取100个左右的临近商家，取在线列表
  size_t total = neighbors.size();
  const size_t MAX_CANDIDATES = 100; // 是个约数

  std::vector<int64_t> selected_neighbors;
  for(std::set<int64_t>::iterator it = neighbors.begin(); it != neighbors.end(); ++it) {
    if ((rand() % total) < MAX_CANDIDATES && (*it != inactive_shop_)) {
      selected_neighbors.push_back(*it);
    }
  }

  std::map<int64_t, SessionType::type> online_map;
  SessionAdapter::Instance().GetOnlineUsers(selected_neighbors, &online_map);

  const size_t MAX_PUSH = 5; // 是个约数
  for(std::map<int64_t, SessionType::type>::iterator it = online_map.begin(); it != online_map.end(); ++it) {
    if ((rand() % online_map.size()) > MAX_PUSH) {
      continue;
    }
    LOG_INFO("BroadcastClient uid=" << uid_ << " to neighbor_shop=" << it->first);
    ret->push_back(it->first);
  }
  LOG_INFO("GetOnlineNeighborShops shop=" << inactive_shop_ << " online neighbor count=" << ret->size() << " city_code=" << city_code
            << " area_code=" << area_code << " quan_code="<< quan_code);
  return 0;
}

void BroadcastClientTask::run() { 
  ShopInfo si = ShopInfoCache::Instance().Get(inactive_shop_);

  {
    ImMessage feedback_message;
    feedback_message.sender = inactive_shop_;
    feedback_message.timestamp = time(NULL);
    SetMessageType(feedback_message, MSG_TYPE_OFFLINE_NOTIFY);
    feedback_message.body = "【360同城帮】您的问题已经发送其他商家，请耐心等待回复。";
    feedback_message.receiver = uid_;

    SessionList sessions;
    SessionAdapter::Instance().GetSessionList(uid_, &sessions, 2);

    for(size_t i = 0; i < sessions.size(); ++i) {
      MessageOutletAdapter::Instance().DistributeMessage(sessions[i].key, feedback_message, 2);
    }
  }

  // 通知导购
  {
    static int64_t customer_guide_ids[] = {317126174, 317124696, 317121850, 317125217};
    int64_t selected_guide = customer_guide_ids[rand() % (sizeof(customer_guide_ids) / sizeof(int64_t))];

    SessionList sessions;
    SessionAdapter::Instance().GetSessionList(selected_guide, &sessions, 2);
    LOG_INFO("offline message guide=" << selected_guide << " session_count=" << sessions.size());
    if (!sessions.empty()) {
      ImMessage guide_message;
      guide_message.sender = uid_;
      guide_message.timestamp = time(NULL);
      SetMessageType(guide_message, MSG_TYPE_OFFLINE_NOTIFY);
      guide_message.body = "【360同城帮】该客户一分钟未收到在线商家回复，需要导购提供帮助。";
      guide_message.receiver = selected_guide;
      for(size_t j = 0; j < sessions.size(); ++j) {
        MessageOutletAdapter::Instance().DistributeMessage(sessions[j].key, guide_message, 2);
      }
    }
  }

  ImMessage broadcast_message;
  broadcast_message.sender = uid_;
  broadcast_message.timestamp = time(NULL);
  SetMessageType(broadcast_message, MSG_TYPE_OFFLINE_NOTIFY);
  broadcast_message.body = "【360同城帮】该客户有修电脑需求，直接回复可以向他提供帮助(5分钟内抢答有效)。";
 
  std::vector<int64_t> online_neighbors;
  GetOnlineNeighborShops(si.city_code, si.area_code, si.quan_code, &online_neighbors);
  if (online_neighbors.size() < 5) {
    GetOnlineNeighborShops(si.city_code, si.area_code, std::string(), &online_neighbors);
  }
  if (online_neighbors.size() < 5) {
    GetOnlineNeighborShops(si.city_code, std::string(), std::string(), &online_neighbors);
  }

  // 给5个左右的在线临近商家推送客户
  for(size_t i = 0; i < online_neighbors.size(); ++i) {
    LOG_INFO("BroadcastClient uid=" << uid_ << " to neighbor_shop=" << online_neighbors[i]);
    
    SessionList sessions;
    SessionAdapter::Instance().GetSessionList(online_neighbors[i], &sessions, 2);
    if (sessions.empty()) {
      continue;
    }
    broadcast_message.receiver = online_neighbors[i];
    for(size_t j = 0; j < sessions.size(); ++j) {
      MessageOutletAdapter::Instance().DistributeMessage(sessions[j].key, broadcast_message, 2);
    }
  }
}

void BroadcastClientWithQuestionTask::run() { 
  if (question_.empty()) {
    LOG_INFO("BroadcastClientWithQuestionTask::run question_is_null");
    BroadcastClientTask::run();
    return;
  }

  LOG_INFO("BroadcastClientWithQuestionTask::run question_is_" << question_);
  ShopInfo si = ShopInfoCache::Instance().Get(inactive_shop_);

  {
    ImMessage feedback_message;
    feedback_message.sender = inactive_shop_;
    feedback_message.timestamp = time(NULL);
    SetMessageType(feedback_message, MSG_TYPE_OFFLINE_NOTIFY);
    feedback_message.body = "【360同城帮】已经向其他商家求助，请耐心等待回复。";
    feedback_message.receiver = uid_;

    SessionList sessions;
    SessionAdapter::Instance().GetSessionList(uid_, &sessions, 2);

    for(size_t i = 0; i < sessions.size(); ++i) {
      MessageOutletAdapter::Instance().DistributeMessage(sessions[i].key, feedback_message, 2);
    }
  }

  // 通知导购
  {
    static int64_t customer_guide_ids[] = {317126174, 317124696, 317121850, 317125217};
    int64_t selected_guide = customer_guide_ids[rand() % (sizeof(customer_guide_ids) / sizeof(int64_t))];

    SessionList sessions;
    SessionAdapter::Instance().GetSessionList(selected_guide, &sessions, 2);
    LOG_INFO("offline message guide=" << selected_guide << " session_count=" << sessions.size());
    if (!sessions.empty()) {
      ImMessage guide_message;
      guide_message.sender = uid_;
      guide_message.timestamp = time(NULL);
      SetMessageType(guide_message, MSG_TYPE_OFFLINE_NOTIFY);
      //guide_message.body = "【360同城帮】该客户一分钟未收到在线商家回复，需要导购提供帮助。\r\n" + question_;
      guide_message.body = question_;
      guide_message.receiver = selected_guide;
      for(size_t j = 0; j < sessions.size(); ++j) {
        MessageOutletAdapter::Instance().DistributeMessage(sessions[j].key, guide_message, 2);
      }
    }

  //sessions.clear();
  //SessionAdapter::Instance().GetSessionList(127646892, &sessions, 2);
  //LOG_INFO("no resp message guide alert 127646892 session_count=" << sessions.size());
  //if (!sessions.empty()) {
  //  ImMessage guide_message;
  //  guide_message.sender = uid_;
  //  guide_message.timestamp = time(NULL);
  //  SetMessageType(guide_message, MSG_TYPE_OFFLINE_NOTIFY);
  //  guide_message.body = "【360同城帮】该客户给商家在线留言无响应，已向" + GetUsername(selected_guide) + "求助。";
  //  guide_message.receiver = 127646892;
  //  for(size_t j = 0; j < sessions.size(); ++j) {
  //    MessageOutletAdapter::Instance().DistributeMessage(sessions[j].key, guide_message, 2);
  //  }
  //}
  }

  ImMessage broadcast_message;
  broadcast_message.sender = uid_;
  broadcast_message.timestamp = time(NULL);
  SetMessageType(broadcast_message, MSG_TYPE_OFFLINE_NOTIFY);
  //broadcast_message.body = "【360同城帮】该客户有修电脑需求，直接回复可以向他提供帮助(5分钟内抢答有效)。\r\n" + question_;
  broadcast_message.body = question_;
 
  std::vector<int64_t> online_neighbors;
  GetOnlineNeighborShops(si.city_code, si.area_code, si.quan_code, &online_neighbors);
  if (online_neighbors.size() < 5) {
    GetOnlineNeighborShops(si.city_code, si.area_code, std::string(), &online_neighbors);
  }
  if (online_neighbors.size() < 5) {
    GetOnlineNeighborShops(si.city_code, std::string(), std::string(), &online_neighbors);
  }

  // 给5个左右的在线临近商家推送客户
  for(size_t i = 0; i < online_neighbors.size(); ++i) {
    LOG_INFO("BroadcastClientWithQuestion uid=" << uid_ << " to neighbor_shop=" << online_neighbors[i] << " question=" << question_);
    
    SessionList sessions;
    SessionAdapter::Instance().GetSessionList(online_neighbors[i], &sessions, 2);
    if (sessions.empty()) {
      continue;
    }
    broadcast_message.receiver = online_neighbors[i];
    for(size_t j = 0; j < sessions.size(); ++j) {
      MessageOutletAdapter::Instance().DistributeMessage(sessions[j].key, broadcast_message, 2);
    }
  }
}

void BangRobotServiceHandler::DispatchMessage(const ImMessage& message) {
  using apache::thrift::concurrency::Runnable;
  GetThreadManager()->add(boost::shared_ptr<Runnable>(new DispatchMessageTask(message)));
}

void BangRobotServiceHandler::DispatchPresence(const int64_t uid, const std::string& session, const SessionType::type type) {
  using apache::thrift::concurrency::Runnable;
  GetThreadManager()->add(boost::shared_ptr<Runnable>(new DispatchPresenceTask(uid, session, type)));
}

void BangRobotServiceHandler::BroadcastClient(const int64_t uid, const int64_t inactive_shop) {
  LOG_INFO("BroadcastClient uid=" << uid << " inactive_shop=" << inactive_shop);
  using apache::thrift::concurrency::Runnable;
  GetThreadManager()->add(boost::shared_ptr<Runnable>(new BroadcastClientTask(uid, inactive_shop)));
}

void BangRobotServiceHandler::BroadcastClientWithQuestion(const int64_t uid, const int64_t inactive_shop, const std::string& question) {
  LOG_INFO("BroadcastClientWithQuestion uid=" << uid << " inactive_shop=" << inactive_shop << " question=" << question);
  using apache::thrift::concurrency::Runnable;
  GetThreadManager()->add(boost::shared_ptr<Runnable>(new BroadcastClientWithQuestionTask(uid, inactive_shop, question)));
}

}


